/**
	Timer class	provides an easy way to time events. Events can be triggered
	repeatedly (like a setInterval) or only once (setTimeout). Or a set number
	of times before expiring. 

	@author Chandler McWilliams
	@version 2005-12-22
	@usage
		<code>		
			// Trace a message every 500 milliseconds.
			var t = new timber.util.Timer(trace, 500, 5, "isn't this fun");
		</code>

*/

class timber.util.Timer
{
	private var duration:Number;
	private var callback:Function;
	private var repeats:Boolean;
	private var repeatCount:Number;
	private var counter:Number;
	private var userInfo:Array;
	private var id:Number;

	/**
		Constructor.

		@param  (Function) newCallback. Callback for when the timer finishes.
		@param  (Number)	 newDuration. Length of timer in milliseconds.
		@param  (Mixed)	 newRepeats. If true, repeat forever, if a number repeat that many times.

	**/
	function Timer (newCallback:Function, newDuration:Number, newRepeats) {
		duration 		= newDuration;
		callback			= newCallback;
		id					= 0;
		
		if (newRepeats === true) {
			repeats 		= true;
			repeatCount = 0;
		} else if ((newRepeats !== false ) && parseInt(newRepeats) != Number.NaN) {
			repeats 		= true;
			repeatCount = parseInt(newRepeats);
			counter		= 0;
		} else {
			repeats 		= false;
		}
		userInfo = arguments.slice(3);
		start();		
	}
	
	/**
		Start the timer with the current counter.
	**/	
	public function start():Void {
		trace('timer start');
		if (id) this.stop();
		id = setInterval(mx.utils.Delegate.create(this, trigger), duration, this);
	}

	/**
		Stop the timer.
	**/
	public function stop():Void {
		trace('timer stop');
		clearInterval(id);
	}

	/**
		Restart the timer with the reset counter.
	**/	
	public function restart():Void {
		this.stop();
		this.reset();
		this.start();
	}
	
	/**
		Reset the timer's counter
	**/
	public function reset():Void {
		counter = 0;
	}

	/**
		Get the timer's current count
	**/
	public function getCounter():Number {
		return counter;
	}


// ===========================================================
// - HANDY
// ===========================================================
	/**
		Returns a timer object that will call the specified method after
		the specified interval.

		@param  time How long to wait before calling the function
		@param  func Function to call
		@return Timer
	*/
	public static function callLater(time:Number, func):Timer {
		return new timber.util.Timer(func, time, false);
	}

	public static function doLater(time:Number, func):Timer {
		return new timber.util.Timer(func, time, false);
	}


// ===========================================================
// - PRIVATE FUNCS
// ===========================================================
	// run each interval
	private function trigger():Void {
		callback.apply(null, userInfo);
		counter++;
		// see if we need to stop
		if (!repeats || (counter == repeatCount)) this.stop();
	}
}

